﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Web.UI;
using System.Web.UI.WebControls;
using StockholmsStad.Web.UI.Class.Controller;
using StockholmsStad.Web.UI.Class.Utilities;
using StockholmsStad.Web.UI.UIServiceReference;

namespace StockholmsStad.Web.UI.Controls.Bokning
{
    /// <summary>
    /// Förstasida för bokningen. Användaren får boka ledig tid och önska dagar som passar
    /// bättre
    /// </summary>
    public partial class Bokning1_ChooseDate : UserControl
    {
        /// <summary>
        /// MVC Controller
        /// </summary>
        public BookingController Controller { get; set; }

        private static bool UpdateSecondPreferredBooking { get; set; }

        /// <summary>
        /// Returnerar ett färdigt bokningsobjekt från sidan 
        /// </summary>
        public Booking Booking
        {
            get
            {
                if (rblTypeOfCeremony.SelectedIndex == 0)
                    return Booking.createOrdinaryBooking(dtfBokning.Checked ? dtfBokning.SelectedDate : null,
                                                         dtfPreferredBooking1.Checked
                                                             ? dtfPreferredBooking1.SelectedDate
                                                             : null,
                                                         dtfPreferredBooking2.Checked
                                                             ? dtfPreferredBooking2.SelectedDate
                                                             : null);
                return Booking.createIndividualBooking(txtIndividualDate.Text, txtBookingCode.Text);
            }
        }

        /// <summary>
        /// Körs när sidan laddas
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!Page.IsPostBack)
            {
                InitializeCeremonies();
                InitializeCachedTimeblocks();

            }
            // Vid ajax-uppdatering tappar controllerna tidblocksinfon vid uppdatering
            InitializeTimeBlocks();
            InitializeStepControl();
            if (!Page.IsPostBack)
            {
                InitializeSelectedDate();
            }

            //Göm/Visa önskat datum 2 beroende på om man valt datum 1
            lblPreferredText2.Visible = dtfPreferredBooking1.Checked;
            dtfPreferredBooking2.Visible = dtfPreferredBooking1.Checked;
            //Om man kryssar ur datum 1 så kryssas även datum 2 ur
            if (!dtfPreferredBooking1.Checked && dtfPreferredBooking2.Checked)
                dtfPreferredBooking2.Checked = false;

            //Validering av att minst ett datum är valt
            if (!dtfBokning.Checked && !dtfPreferredBooking1.Checked && !dtfPreferredBooking2.Checked)
            {
                lblSelectAtLeastOneDate.Visible = true;
            }
            else
            {
                lblSelectAtLeastOneDate.Visible = false;
            }   
        }

        private void InitializeCachedTimeblocks()
        {
            Controller.InitializeCachedTimeblocks();
        }

        private void InitializeTimeBlocks()
        {
            if (Controller.CachedFreeTimeblocksOrdinary == null || 
                Controller.CachedFreeTimeblocksIndividual == null)
            {
                InitializeCachedTimeblocks();
            }
            bdlFreeTimes.Items.Clear();
            bool ordinary = rblTypeOfCeremony.SelectedValue == ((int)CeremonyType.Ordinary).ToString(); 
            IOrderedEnumerable<DateTime> timeblocks = ordinary ? Controller.CachedFreeTimeblocksOrdinary : Controller.CachedFreeTimeblocksIndividual;
            if (timeblocks != null)
            {
                if (timeblocks.Count() == 0)
                {
                    lblTenClosestDays.Visible = false;
                    lblNoFreeTimes.Visible = true;
                }
                else
                {
                    lblTenClosestDays.Visible = true;
                    lblNoFreeTimes.Visible = false;
                    //Kalendrar
                    clrDatePickerIndividual.TodaysDate = timeblocks.FirstOrDefault();
                    clrDatePickerOrdinary.TodaysDate = timeblocks.FirstOrDefault();
                }
                bdlFreeTimes.Items.AddRange(DateTimeUtil.GetFirstListItems(10, timeblocks, GetDateTimeLinkText));
                dtfBokning.Dates = timeblocks;
            }
            dtfPreferredBooking1.Dates = Controller.CachedBookedTimeblocks;
            dtfPreferredBooking2.Dates = Controller.CachedBookedTimeblocks;
        }

        private void InitializeSelectedDate()
        {
            Booking booking = Controller.Booking;
            bool ordinary = booking.CeremonyType == CeremonyType.Ordinary;
            dtfBokning.SelectedDate = ordinary && booking.DateTime != null
                                          ? booking.DateTime.StartDateTime
                                          : (DateTime?) null;
            dtfPreferredBooking1.SelectedDate = ordinary && booking.PreferredDate1 != null
                                                    ? booking.PreferredDate1
                                                    : (DateTime?) null;
            dtfPreferredBooking2.SelectedDate = ordinary && booking.PreferredDate2 != null
                                                    ? booking.PreferredDate2
                                                    : (DateTime?) null;
            if (!ordinary && booking.DateTime != null)
            {
                txtIndividualDate.Text = GetDateText(booking.DateTime.StartDateTime);
                txtBookingCode.Text = booking.MinisterCode;
            }
            ShowCeremonyTypePanel(ordinary);
        }
        private void InitializeStepControl()
        {
            BookingSteps.Clear();
            BookingSteps.AddStep("Välj tid", true, false);
            BookingSteps.AddStep("Bekräfta bokning", false, false);
            BookingSteps.Refresh();
        }
        private void InitializeCeremonies()
        {
            IList<ValueIdPair> types = Controller.CeremonyTypes;
            foreach (ValueIdPair type in types)
            {
                if (type.Id == (int)CeremonyType.Ordinary)
                {
                    type.Name = "Ceremoni i stadshuset";
                }
                if (type.Id == (int)CeremonyType.Individual)
                {
                    type.Name = "Ceremoni annan plats";
                    type.Description = "För att boka denna typ av ceremoni behöver ni en kod från förättaren";
                }
            }
            rblTypeOfCeremony.Items.Clear();
            rblTypeOfCeremony.Items.AddRange(types.Select(pair => new ListItem(pair.Name, pair.Id.ToString())).ToArray());
            rblTypeOfCeremony.SelectedIndex = 0;
        }

        /// <summary>
        /// Typ av ceremoni (individuell eller ordinarie) har ändrats
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void rblTypeOfCeremony_SelectedIndexChanged(object sender, EventArgs e)
        {
            bool ordinary = rblTypeOfCeremony.SelectedValue == ((int) CeremonyType.Ordinary).ToString();
            ShowCeremonyTypePanel(ordinary);
        }

        private void ShowCeremonyTypePanel(bool ordinary)
        {
            pnlCeremonyOrdinary.Visible = ordinary;
            pnlCeremonyIndividual.Visible = !ordinary;
            rblTypeOfCeremony.SelectedIndex = ordinary ? 0 : 1;
        }

        /// <summary>
        /// Rendering av kalender. Väljer ut klickbara dagar i kalendern för individuell bokning
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void clrDatePickerIndividual_DayRender(object sender, DayRenderEventArgs e)
        {
            // Disable all dates before todays date
            CalendarDay day = e.Day;
            //if (day.Date <= DateTime.Now)
            if (day.Date < clrDatePickerIndividual.TodaysDate)
            {
                day.IsSelectable = false;
                e.Cell.CssClass = "calendar-cell-disabled";
            }
        }

        /// <summary>
        /// Användaren har valt ett datum i kalendern för individuell bokning
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void clrDatePickerIndividual_SelectionChanged(object sender, EventArgs e)
        {
            // Let the calendar populate the textbox
            txtIndividualDate.Text = clrDatePickerIndividual.SelectedDate.ToString("yyyy-MM-dd");
        }

        /// <summary>
        /// Användaren har valt ett datum i kalendern för ordinarie bokning
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void clrDatePickerOrdinary_SelectionChanged(object sender, EventArgs e)
        {
            // Extract choosen date
            DateTime date = clrDatePickerOrdinary.SelectedDate;
            // Check if the date is booked
            DateTime? bookedDate = DateTimeUtil.GetFirstYearAndDayMatch(date, Controller.CachedBookedTimeblocks);
            if (bookedDate != null)
            {
                if (UpdateSecondPreferredBooking)
                {
                    dtfPreferredBooking2.SelectedDate = bookedDate;
                }
                else
                {
                    dtfPreferredBooking1.SelectedDate = bookedDate;
                }
                // Alternate update of the preferred booking fields
                UpdateSecondPreferredBooking = !UpdateSecondPreferredBooking;
                return;
            }
            // Check if the date is free
            DateTime? freeDate = DateTimeUtil.GetFirstYearAndDayMatch(date, Controller.CachedFreeTimeblocksOrdinary);
            if (freeDate != null)
            {
                dtfBokning.SelectedDate = freeDate;
                return;
            }
            // Could not find date
        }


        /// <summary>
        /// Rendering av kalender. Väljer ut klickbara dagar i kalendern för individuell bokning
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void clrDatePickerOrdinary_DayRender(object sender, DayRenderEventArgs e)
        {
            DateTime date = e.Day.Date;
            // Disable all dates before todays date
            if (date <= DateTime.Now)
            {
                e.Day.IsSelectable = false;
                e.Cell.CssClass = "calendar-cell-disabled";
                return;
            }
            // Check if the date is booked
            DateTime? bookedDate = DateTimeUtil.GetFirstYearAndDayMatch(date, Controller.CachedBookedTimeblocks);
            if (bookedDate != null)
            {
                // Tyvärr verkar cssclassen bara få genomslag på genererad td och inte
                // på underliggande a-tagg
                e.Cell.CssClass = "calendar-cell-booked";
                e.Cell.ForeColor = Color.Red;
                return;
            }
            // Check if the date is free
            DateTime? freeDate = DateTimeUtil.GetFirstYearAndDayMatch(date, Controller.CachedFreeTimeblocksOrdinary);
            if (freeDate != null)
            {
                // Tyvärr verkar cssclassen bara få genomslag på genererad td och inte
                // på underliggande a-tagg
                e.Cell.CssClass = "calendar-cell-free";
                e.Cell.ForeColor = Color.Green;
                return;
            }
            // The rest of the days are not bookable
            e.Day.IsSelectable = false;
            e.Cell.CssClass = "calendar-cell-disabled";
        }

        /// <summary>
        /// Användaren har valt ett datum ur listan över lediga tider för ordinarie bokning
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void bdlFreeTimes_Click(object sender, BulletedListEventArgs e)
        {
            // If the user selects a date from the list of free dates
            var date = new DateTime(long.Parse(bdlFreeTimes.Items[e.Index].Value));
            dtfBokning.SelectedDate = date;
        }

        private static string GetDateTimeLinkText(DateTime date)
        {
            return date.ToString("yyyy-MM-dd HH:mm »");
        }

        private static string GetDateText(DateTime dateTime)
        {
            return dateTime.ToString("yyyy-MM-dd");
        }

        /// <summary>
        /// Validerar att bokningskoden tillhör en förrättare.
        /// </summary>
        /// <param name="source"></param>
        /// <param name="args"></param>
        protected void txtBookingCodeCustomValidator_ServerValidate(object source, ServerValidateEventArgs args)
        {
            args.IsValid = Controller.IsBookingCodeValid(txtBookingCode.Text);
        }
    }
}